﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Newtonsoft.Json;
using orienta.Code.JQgrid;
using orienta.Code;

namespace orienta.Utils
{
    public class Utils
    {
        public static string GetWhere(string filters, List<Rule> rules)
        {
            var where = string.Empty;
            var filtro = (string.IsNullOrEmpty(filters)) ? null : JsonConvert.DeserializeObject<Filter>(filters);

            if ((filtro != null))
            {
                where = ConvertToSql(filtro);
            }

            if ((rules != null))
            {
                foreach (var regla in rules.Where(regla => (!(string.IsNullOrEmpty(regla.data)) & regla.data != "0")))
                {
                    if (string.IsNullOrEmpty(regla.op))
                    {
                        regla.op = "=";
                    }
                    where += " and " + regla.field + regla.op + regla.data;
                }
            }

            return string.IsNullOrEmpty(@where) ? where : (where.StartsWith(" and ") ? where.Substring(4) : where);
        }

        protected String GetWhere(string columna, string operacion, string valor)
        {
            var opciones = new Dictionary<string, string>();
            {
                opciones.Add("eq", "=");
                opciones.Add("ne", "<>");
                opciones.Add("lt", "<");
                opciones.Add("le", "<=");
                opciones.Add("gt", ">");
                opciones.Add("ge", ">=");
                opciones.Add("bw", "LIKE");
                opciones.Add("bn", "NOT LIKE");
                opciones.Add("in", "LIKE");
                opciones.Add("ni", "NOT LIKE");
                opciones.Add("ew", "LIKE");
                opciones.Add("en", "NOT LIKE");
                opciones.Add("cn", "LIKE");
                opciones.Add("nc", "NOT LIKE");
                opciones.Add("fe", "NOT LIKE");
            }

            if (string.IsNullOrEmpty(operacion))
            {
                return string.Empty;
            }

            if (operacion.Equals("bw") || operacion.Equals("bn"))
            {
                valor = valor + "%";
            }
            if (operacion.Equals("ew") || operacion.Equals("en"))
            {
                valor = "%" + valor;
            }
            if (operacion.Equals("cn") || operacion.Equals("nc") || operacion.Equals("in") || operacion.Equals("ni"))
            {
                valor = "%" + valor + "%";
            }
            if (opciones.Take(6).ToDictionary(p => p.Key, p => p.Value).ContainsKey(operacion))
            {
                return string.IsNullOrEmpty(valor) ? string.Empty : (columna + " ") + opciones[operacion] + " " + valor;
            }
            if (operacion.Equals("fe"))
            {
                valor = String.Format("{0:yyyy-MM-dd}", valor);
            }

            return columna + " " + opciones[operacion] + " '" + valor + "'";
        }

        public static string ConvertToSql(Filter filtros)
        {
            var whereFiltro = string.Empty;

            var valor = string.Empty;
            if (filtros.rules == null)
            {
                filtros.rules = new List<Rule>();
            }

            foreach (var filtro in filtros.rules)
            {
                valor = string.Empty;
                var filterFormatString = string.Empty;

                switch (filtro.op)
                {
                    case "bw":
                        filterFormatString = " {0} {1} like '{2}%'";
                        valor = filtro.data;
                        break; // TODO: might not be correct. Was : Exit Select

                    //equal ==
                    case "eq":
                        filterFormatString = " {0} {1} = {2}";
                        valor = filtro.data;
                        break; // TODO: might not be correct. Was : Exit Select

                    //not equal !=
                    case "ne":
                        filterFormatString = " {0} {1} <> {2}";
                        valor = filtro.data;
                        break; // TODO: might not be correct. Was : Exit Select

                    //string.Contains()
                    case "cn":
                        filterFormatString = " {0} {1} like '%{2}%'";
                        valor = filtro.data;
                        break; // TODO: might not be correct. Was : Exit Select

                    case "fe":
                        filterFormatString = " {0} Cast({1} as date) = '{2}'";
                        valor = formatearFecha(filtro.data);
                        break; // TODO: might not be correct. Was : Exit Select
                }

                whereFiltro += string.Format(filterFormatString, filtros.groupOp, filtro.field, valor);
            }

            return filtros.rules.Count() == 0 ? string.Empty : whereFiltro.Substring(4);
        }

        public GenericDouble<JQgrid, T> Listar<T>(IBase<T> logic, string sidx, string sord, int page, int rows, bool search, string searchField, string searchOper, string searchString, string @where) where T : class
        {
            var jqgrid = new JQgrid();
            IList<T> list;

            try
            {
                int totalPages = 0;

                if (search)
                {
                    @where = @where + GetWhere(searchField, searchOper, searchString);
                }

                var count = logic.Count(@where);

                if (count > 0 && rows > 0)
                {
                    if (count % rows > 0)
                    {
                        totalPages = (int)Math.Ceiling((decimal)(count / rows));
                        totalPages = (int)(count / rows) + 1;
                    }
                    else
                    {
                        totalPages = (int)(count / rows);
                    }
                    //totalPages = (int)Math.Ceiling((decimal)(count / rows));
                    totalPages = totalPages == 0 ? 1 : totalPages;
                }

                page = page > totalPages ? totalPages : page;

                var start = rows * page - rows;
                if (start < 0)
                {
                    start = 0;
                }

                jqgrid.total = totalPages;
                jqgrid.page = page;
                jqgrid.records = count;
                jqgrid.start = start;

                list = logic.GetAll(sidx, sord, rows, page, @where);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return new GenericDouble<JQgrid, T>(jqgrid, list);
        }

        public static string formatearFecha(string fecha)
        {
            var date = fecha.Split('/');
            return string.Format("{0}-{1}-{2}", date[2].ToString(), date[1].ToString(), date[0].ToString());

        }
    }
}